# !/usr/bin/env python
# -*-coding:utf-8 -*-

"""
# File       : Pythoner.py
# Time       ：2023/12/12 22:45
# Author     ：Y-aong
# version    ：python 3.10
# Description：
"""
import gc
import os
import sys

from builtins import exec as run

from pydantic import Field

from conf.config import OrderLinesConfig
from orderlines.libraries.BaseTask import BaseTask
from orderlines.utils.base_orderlines_type import BasePluginParam
from public.logger import logger


class PythonCodeParam(BasePluginParam):
    python_code: str = Field(description='python代码-code')


class PythonFileParam(BasePluginParam):
    python_file: str = Field(description='python脚本-upload')


class PythonNameSpace(object):

    def __init__(self):
        self.__old_modules = sys.modules.copy()
        self.__old_environs = os.environ.copy()
        self.__old_globals = globals().copy()
        self.__old_paths = sys.path.copy()

    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_val, exc_tb):
        modules_diff = set(set(sys.modules.keys()) - set(self.__old_modules.keys()))
        for key in modules_diff:
            sys.modules.pop(key)
        environs_diff = set(set(os.environ.keys()) - set(self.__old_environs.keys()))
        for key in environs_diff:
            os.environ.pop(key)
        globals_diff = set(set(globals().keys()) - set(self.__old_globals.keys()))
        for key in globals_diff:
            globals().pop(key)
        sys_path_diff = set(sys.path).symmetric_difference(set(self.__old_paths))
        sys.path = list(set(sys.path))  # 防止路径重复插入，先去重
        for p in sys_path_diff:
            sys.path.remove(p)
        gc.collect()


class Pythoner(BaseTask):
    version = OrderLinesConfig.version
    title = '运行python'
    category = '内置功能'
    icon = 'Tools'

    def __init__(self):
        super(Pythoner, self).__init__()

    def run_code(self, param: PythonCodeParam):
        """
        py代码
        @param param:
        @return:
        """
        print(param.model_dump())
        global_dict = {
            'task_config': param.task_config,
            'task_instance_id': param.task_instance_id
        }
        return self._run_code(param.python_code, global_dict)

    def _run_code(self, code: str, global_dict: dict):
        with PythonNameSpace():
            run(code, global_dict)
        logger.info(f'运行python返回值::{global_dict.get("value")}')
        if isinstance(global_dict.get("value"), dict):
            return {'status': self.success, **global_dict.get("value")}
        else:
            return {'status': self.success, 'value': global_dict.get("value")}

    def run_script(self, param: PythonFileParam):
        """
        py脚本
        @param param:
        @return:
        """
        global_dict = {
            'task_config': param.task_config,
            'task_instance_id': param.task_instance_id
        }
        with open(file=param.python_file, encoding='utf-8') as f:
            code = f.read()
        return self._run_code(code, global_dict)
